using System;
using System.Collections.Generic;
using LinFu.IoC.Configuration;

namespace CoreEx.MicroMapper.Implementation
{
    [Implements(typeof (IAccessor), LifecycleType.Singleton, ServiceName = "PropertyAccessor")]
    public class PropertyAccessor : IAccessor
    {
        private readonly IDictionary<Type, ILateBinder> _lateBinders = new Dictionary<Type, ILateBinder>();       

        private ILateBinder GetLateBinder(Type type)
        {
            if (!_lateBinders.ContainsKey(type))
                _lateBinders.Add(type, new LateBinder(type));
            return _lateBinders[type];
        }

        /// <summary>
        /// Invokes the property getter on the given property name.
        /// </summary>
        /// <param name="target">The target object for to get the property value</param>
        /// <param name="accessorInfo">The <see cref="IAccessorInfo"/> that describes the accessor.</param>
        /// <returns>The property value.</returns>
        public object GetValue(object target, IAccessorInfo accessorInfo)
        {
            return GetLateBinder(target.GetType()).GetPropertyValue(target, accessorInfo.Name);            
        }

        /// <summary>
        /// Invokes the property setter on the given property name.
        /// </summary>
        /// <param name="target">The target object for to set the value.</param>
        /// <param name="accessorInfo">The <see cref="IAccessorInfo"/> that describes the accessor.</param>
        /// <param name="value">The property value to set.</param>
        public void SetValue(object target, IAccessorInfo accessorInfo, object value)
        {
            GetLateBinder(target.GetType()).SetPropertyValue(target, accessorInfo.Name, value);
        }
    }
}